package utils

import (
	"context"
	"crypto/tls"
	"fmt"
	"io"
	"net/http"
	"net/url"
	"strings"
	"time"
)

// LinkVerificationResult 链接验证结果
type LinkVerificationResult struct {
	URL           string        `json:"url"`
	Success       bool          `json:"success"`
	StatusCode    int           `json:"status_code"`
	Content       string        `json:"content"`
	ContentType   string        `json:"content_type"`
	ContentLength int64         `json:"content_length"`
	ResponseTime  time.Duration `json:"response_time"`
	RedirectCount int           `json:"redirect_count"`
	FinalURL      string        `json:"final_url"`
	Error         string        `json:"error,omitempty"`
}

// ProtocolVerificationResult 协议验证结果
type ProtocolVerificationResult struct {
	HTTP  *LinkVerificationResult `json:"http,omitempty"`
	HTTPS *LinkVerificationResult `json:"https,omitempty"`
}

// ContentResult 内容获取结果
type ContentResult struct {
	URL         string    `json:"url"`
	Body        string    `json:"body"`
	ContentType string    `json:"content_type"`
	StatusCode  int       `json:"status_code"`
	FetchTime   time.Time `json:"fetch_time"`
}

// LinkVerifier 链接验证器
type LinkVerifier struct {
	httpClient      *http.Client
	httpsClient     *http.Client
	timeout         time.Duration
	maxRedirects    int
	maxContentLen   int64
	insecureTLS     bool
	followRedirects bool
	redirectCount   int
}

// LinkVerifierOption 配置选项
type LinkVerifierOption func(*LinkVerifier)

// WithInsecureTLS 允许不安全的 TLS（忽略证书错误）
func WithInsecureTLS(insecure bool) LinkVerifierOption {
	return func(v *LinkVerifier) {
		v.insecureTLS = insecure
	}
}

// WithFollowRedirects 设置是否跟随重定向
func WithFollowRedirects(follow bool) LinkVerifierOption {
	return func(v *LinkVerifier) {
		v.followRedirects = follow
	}
}

// WithMaxRedirects 设置最大重定向次数
func WithMaxRedirects(max int) LinkVerifierOption {
	return func(v *LinkVerifier) {
		v.maxRedirects = max
	}
}

// NewLinkVerifier 创建链接验证器
func NewLinkVerifier(opts ...LinkVerifierOption) *LinkVerifier {
	v := &LinkVerifier{
		timeout:         10 * time.Second,
		maxRedirects:    10,
		maxContentLen:   1024 * 1024, // 1MB
		insecureTLS:     false,       // 默认安全模式（严格 TLS）
		followRedirects: true,        // 默认跟随重定向
	}

	// 应用选项
	for _, opt := range opts {
		opt(v)
	}

	// 配置重定向策略
	checkRedirect := func(req *http.Request, via []*http.Request) error {
		if !v.followRedirects {
			return http.ErrUseLastResponse
		}
		v.redirectCount = len(via)
		if len(via) >= v.maxRedirects {
			return fmt.Errorf("too many redirects (%d)", len(via))
		}
		return nil
	}

	// HTTP客户端
	v.httpClient = &http.Client{
		Timeout:       v.timeout,
		CheckRedirect: checkRedirect,
	}

	// HTTPS客户端
	transport := &http.Transport{}
	if v.insecureTLS {
		transport.TLSClientConfig = &tls.Config{
			InsecureSkipVerify: true,
		}
	}

	v.httpsClient = &http.Client{
		Timeout:       v.timeout,
		CheckRedirect: checkRedirect,
		Transport:     transport,
	}

	return v
}

// SetTimeout 设置超时时间
func (v *LinkVerifier) SetTimeout(timeout time.Duration) {
	v.timeout = timeout
	v.httpClient.Timeout = timeout
	v.httpsClient.Timeout = timeout
}

// SetMaxRedirects 设置最大重定向次数
func (v *LinkVerifier) SetMaxRedirects(max int) {
	v.maxRedirects = max
}

// checkRedirect 检查重定向
func (v *LinkVerifier) checkRedirect(req *http.Request, via []*http.Request) error {
	if len(via) >= v.maxRedirects {
		return fmt.Errorf("too many redirects (%d)", len(via))
	}
	return nil
}

// Verify 验证链接
func (v *LinkVerifier) Verify(ctx context.Context, urlStr string) (*LinkVerificationResult, error) {
	if urlStr == "" {
		return nil, fmt.Errorf("URL cannot be empty")
	}

	// 解析URL
	parsedURL, err := url.Parse(urlStr)
	if err != nil {
		return nil, fmt.Errorf("invalid URL: %v", err)
	}

	// 选择客户端
	client := v.httpClient
	if parsedURL.Scheme == "https" {
		client = v.httpsClient
	}

	// 创建请求
	req, err := http.NewRequestWithContext(ctx, "GET", urlStr, nil)
	if err != nil {
		return nil, fmt.Errorf("failed to create request: %v", err)
	}

	// 设置User-Agent
	req.Header.Set("User-Agent", "DNS-Tools/1.0")

	// 执行请求
	start := time.Now()
	resp, err := client.Do(req)
	responseTime := time.Since(start)

	if err != nil {
		// 检查是否是重定向错误
		if strings.Contains(err.Error(), "too many redirects") {
			return nil, err
		}
		return &LinkVerificationResult{
			URL:          urlStr,
			Success:      false,
			ResponseTime: responseTime,
			Error:        err.Error(),
		}, nil
	}
	defer resp.Body.Close()

	// 读取内容
	body, err := io.ReadAll(io.LimitReader(resp.Body, v.maxContentLen))
	if err != nil {
		return &LinkVerificationResult{
			URL:          urlStr,
			Success:      false,
			StatusCode:   resp.StatusCode,
			ResponseTime: responseTime,
			Error:        fmt.Sprintf("failed to read response: %v", err),
		}, nil
	}

	// 获取最终 URL
	finalURL := urlStr
	if resp.Request != nil && resp.Request.URL != nil {
		finalURL = resp.Request.URL.String()
	}

	result := &LinkVerificationResult{
		URL:           urlStr,
		Success:       resp.StatusCode >= 200 && resp.StatusCode < 400,
		StatusCode:    resp.StatusCode,
		Content:       string(body),
		ContentType:   resp.Header.Get("Content-Type"),
		ContentLength: resp.ContentLength,
		ResponseTime:  responseTime,
		RedirectCount: v.redirectCount, // 使用实际统计的重定向次数
		FinalURL:      finalURL,
	}

	// 重置计数器
	v.redirectCount = 0

	return result, nil
}

// VerifyWithProtocols 使用HTTP和HTTPS协议验证链接
func (v *LinkVerifier) VerifyWithProtocols(ctx context.Context, urlStr string) (*ProtocolVerificationResult, error) {
	if urlStr == "" {
		return nil, fmt.Errorf("URL cannot be empty")
	}

	// 解析URL获取基础部分
	parsedURL, err := url.Parse(urlStr)
	if err != nil {
		return nil, fmt.Errorf("invalid URL: %v", err)
	}

	result := &ProtocolVerificationResult{}

	// 构建HTTP和HTTPS URLs
	httpURL := urlStr
	httpsURL := urlStr

	if strings.HasPrefix(urlStr, "//") {
		httpURL = "http:" + urlStr
		httpsURL = "https:" + urlStr
	} else if parsedURL.Scheme == "" {
		httpURL = "http://" + urlStr
		httpsURL = "https://" + urlStr
	} else if parsedURL.Scheme == "http" {
		httpsURL = strings.Replace(urlStr, "http://", "https://", 1)
	} else if parsedURL.Scheme == "https" {
		httpURL = strings.Replace(urlStr, "https://", "http://", 1)
	}

	// 并发测试两个协议
	type protocolResult struct {
		isHTTPS bool
		result  *LinkVerificationResult
		err     error
	}

	results := make(chan protocolResult, 2)

	// 测试HTTP
	go func() {
		res, err := v.Verify(ctx, httpURL)
		results <- protocolResult{isHTTPS: false, result: res, err: err}
	}()

	// 测试HTTPS
	go func() {
		res, err := v.Verify(ctx, httpsURL)
		results <- protocolResult{isHTTPS: true, result: res, err: err}
	}()

	// 收集结果
	for i := 0; i < 2; i++ {
		pr := <-results
		if pr.isHTTPS {
			result.HTTPS = pr.result
		} else {
			result.HTTP = pr.result
		}
	}

	return result, nil
}

// FetchContent 获取链接内容
func (v *LinkVerifier) FetchContent(ctx context.Context, urlStr string) (*ContentResult, error) {
	if urlStr == "" {
		return nil, fmt.Errorf("URL cannot be empty")
	}

	// 创建请求
	req, err := http.NewRequestWithContext(ctx, "GET", urlStr, nil)
	if err != nil {
		return nil, fmt.Errorf("failed to create request: %v", err)
	}

	// 设置User-Agent
	req.Header.Set("User-Agent", "DNS-Tools/1.0")

	// 选择客户端
	client := v.httpClient
	if strings.HasPrefix(urlStr, "https://") {
		client = v.httpsClient
	}

	// 执行请求
	resp, err := client.Do(req)
	if err != nil {
		return nil, fmt.Errorf("request failed: %v", err)
	}
	defer resp.Body.Close()

	// 读取内容
	body, err := io.ReadAll(io.LimitReader(resp.Body, v.maxContentLen))
	if err != nil {
		return nil, fmt.Errorf("failed to read response: %v", err)
	}

	result := &ContentResult{
		URL:         urlStr,
		Body:        string(body),
		ContentType: resp.Header.Get("Content-Type"),
		StatusCode:  resp.StatusCode,
		FetchTime:   time.Now(),
	}

	return result, nil
}
